import express from "express";
import multer from "multer";
import fs from "fs";
import path from "path";
import os from "os";
import archiver from "archiver";
import mime from "mime-types";

const app = express();
const __dirname = process.cwd();
const UPLOADS_DIR = path.join(__dirname, "uploads");

// 在初始化时只创建 UPLOADS_DIR
if (!fs.existsSync(UPLOADS_DIR)) fs.mkdirSync(UPLOADS_DIR, { recursive: true });

// 上传配置（修复中文乱码）
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    const currentPath = decodeURIComponent(req.query.path || "");
    const targetDir = path.join(UPLOADS_DIR, currentPath);
    
    // 安全检查：确保目标目录在 uploads 目录内
    if (!targetDir.startsWith(UPLOADS_DIR + path.sep) && targetDir !== UPLOADS_DIR) {
      return cb(new Error("Invalid path"));
    }
    
    fs.mkdirSync(targetDir, { recursive: true });
    cb(null, targetDir);
  },
  filename: (req, file, cb) => {
    const originalName = Buffer.from(file.originalname, "latin1").toString("utf8");
    
    // 安全检查：防止路径遍历攻击
    if (originalName.includes("..") || originalName.includes("/") || originalName.includes("\\")) {
      return cb(new Error("Invalid filename"));
    }
    
    cb(null, originalName);
  },
});
const upload = multer({ storage });

// 添加错误处理中间件
app.use((error, req, res, next) => {
  if (error instanceof multer.MulterError) {
    console.error("Upload error:", error);
    return res.status(400).send("Upload failed: " + error.message);
  } else if (error) {
    console.error("Upload error:", error);
    return res.status(400).send("Upload failed: " + error.message);
  }
  next();
});

// 获取本机局域网 IP
function getLocalIP() {
  const nets = os.networkInterfaces();
  for (const name of Object.keys(nets)) {
    for (const net of nets[name] || []) {
      // 修复：添加额外的检查确保地址有效
      if (net.family === "IPv4" && !net.internal && net.address) {
        return net.address;
      }
    }
  }
  // 如果找不到局域网IP，返回一个明确的信息而不是"localhost"
  return "无法获取局域网IP";
}

// 获取目录下文件列表
function readFolder(dir) {
  // 添加安全检查
  if (!fs.existsSync(dir)) {
    return [];
  }
  
  const items = fs.readdirSync(dir, { withFileTypes: true });
  return items
    .map((item) => ({
      name: item.name,
      type: item.isDirectory() ? "folder" : "file",
      size: item.isDirectory()
        ? "-"
        : (fs.statSync(path.join(dir, item.name)).size / 1024).toFixed(1) + " KB",
    }));
}

// 渲染主页面
app.get("/", (req, res) => {
  res.setHeader("Content-Type", "text/html; charset=utf-8");

  const currentPath = decodeURIComponent(req.query.path || "");
  const absPath = path.join(UPLOADS_DIR, currentPath);

  // 加强安全检查
  if (!absPath.startsWith(UPLOADS_DIR + path.sep) && absPath !== UPLOADS_DIR) {
    return res.status(403).send("Access denied.");
  }

  // 检查路径是否存在
  if (!fs.existsSync(absPath)) {
    return res.status(404).send("Path not found.");
  }

  const files = readFolder(absPath);
  const parentPath =
    currentPath && currentPath !== "" ? path.dirname(currentPath) : "";

  res.send(renderPage(files, currentPath, parentPath));
});

// 上传文件
app.post("/upload", upload.array("files"), (req, res) => {
  res.redirect(req.get("referer") || "/");
});

// 删除（永久删除）
app.post("/delete", express.urlencoded({ extended: true }), (req, res) => {
  const { path: currentPath, name } = req.body;
  
  // 安全检查
  if (!name || name.includes("..") || name.includes("/") || name.includes("\\")) {
    return res.status(400).send("Invalid filename");
  }
  
  const target = path.join(UPLOADS_DIR, currentPath, name);
  
  // 安全检查：确保目标在 uploads 目录内
  if (!target.startsWith(UPLOADS_DIR + path.sep)) {
    return res.status(403).send("Access denied.");
  }
  
  if (!fs.existsSync(target)) return res.redirect(req.get("referer") || "/");
  
  // 确保不会删除 uploads 根目录
  if (target === UPLOADS_DIR) {
    return res.status(400).send("Cannot delete root directory");
  }
  
  // 永久删除文件或目录
  try {
    const stat = fs.statSync(target);
    if (stat.isDirectory()) {
      fs.rmSync(target, { recursive: true, force: true });
    } else {
      fs.unlinkSync(target);
    }
  } catch (error) {
    console.error("Delete error:", error);
    return res.status(500).send("Failed to delete file or directory");
  }
  
  res.redirect(req.get("referer") || "/");
});

// 创建文件夹
app.post("/mkdir", express.urlencoded({ extended: true }), (req, res) => {
  const { path: currentPath, name } = req.body;
  
  // 安全检查
  if (!name || name.includes("..") || name.includes("/") || name.includes("\\") || name.includes("\0")) {
    return res.status(400).send("Invalid folder name");
  }
  
  // 限制文件夹名称长度
  if (name.length > 255) {
    return res.status(400).send("Folder name too long");
  }
  
  const dirPath = path.join(UPLOADS_DIR, currentPath, name);
  
  // 安全检查：确保目标在 uploads 目录内
  if (!dirPath.startsWith(UPLOADS_DIR + path.sep)) {
    return res.status(403).send("Access denied.");
  }
  
  if (!fs.existsSync(dirPath)) fs.mkdirSync(dirPath, { recursive: true });
  res.redirect(req.get("referer") || "/");
});

// 下载单个文件
app.get("/download", (req, res) => {
  const { path: currentPath, name } = req.query;
  const filePath = path.join(UPLOADS_DIR, currentPath, name);
  if (!fs.existsSync(filePath)) return res.status(404).send("Not Found");
  res.download(filePath, name);
});

// 压缩当前目录为 ZIP
app.get("/zip", (req, res) => {
  try {
    const currentPath = decodeURIComponent(req.query.path || "");
    const dirPath = path.join(UPLOADS_DIR, currentPath);
    
    // 安全检查：确保路径在 uploads 目录内
    if (!dirPath.startsWith(UPLOADS_DIR)) {
      return res.status(403).send("Access denied.");
    }
    
    // 检查目录是否存在
    if (!fs.existsSync(dirPath)) {
      return res.status(404).send("Directory not found.");
    }
    
    const zipName = (currentPath ? currentPath.replace(/[\\/]/g, "_") : "root") + ".zip";

    res.setHeader("Content-Disposition", `attachment; filename="${zipName}"`);
    res.setHeader("Content-Type", "application/zip");

    const archive = archiver("zip", { zlib: { level: 9 } });
    
    // 监听错误事件
    archive.on("error", (err) => {
      console.error("Zip error:", err);
      res.status(500).send("Failed to create zip archive.");
    });
    
    archive.directory(dirPath, false);
    archive.pipe(res);
    archive.finalize();
  } catch (error) {
    console.error("Zip error:", error);
    res.status(500).send("Failed to create zip archive.");
  }
});

// 渲染页面（美化 + 功能区）
function renderPage(files, currentPath, parentPath) {
  return `
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<title>📂 局域网文件共享</title>
<style>
  body { font-family: 'Segoe UI',sans-serif;background:#f5f6fa;margin:0;padding:20px; }
  .container { background:#fff;border-radius:12px;padding:20px;box-shadow:0 3px 8px rgba(0,0,0,0.1);}
  h1 { display:flex;justify-content:space-between;align-items:center;font-size:20px;margin:0 0 10px; }
  .toolbar { display:flex;gap:10px;flex-wrap:wrap;margin-bottom:15px; }
  button { padding:6px 12px;border:none;border-radius:6px;cursor:pointer;font-size:14px;transition:0.2s; }
  .btn-upload{background:#007bff;color:#fff;}
  .btn-folder{background:#17a2b8;color:#fff;}
  .btn-zip{background:#ffc107;color:#333;}
  .btn-delete{background:#dc3545;color:#fff;}
  .btn-back{background:#6c757d;color:#fff;}
  button:hover{opacity:0.85;}
  table{width:100%;border-collapse:collapse;margin-top:10px;}
  th{text-align:left;}
  th,td{padding:10px;border-bottom:1px solid #eee;}
  tr:hover{background:#f9f9f9;}
  .folder{color:#007bff;text-decoration:none;font-weight:500;}
  .file{color:#333;}
  form.inline{display:inline;}
</style>
</head>
<body>
<div class="container">
  <h1>📁 当前路径：/${currentPath || ""} 
  ${currentPath ? `<a href="/?path=${encodeURIComponent(parentPath)}"><button class="btn-back">⬅ 返回上级</button></a>` : ""}
  </h1>

  <div class="toolbar">
    <form class="inline" action="/upload?path=${encodeURIComponent(currentPath)}" method="post" enctype="multipart/form-data">
      <input type="file" name="files" multiple required />
      <button class="btn-upload" type="submit">上传文件</button>
    </form>
    <form class="inline" action="/mkdir" method="post" onsubmit="return createFolder(this)">
      <input type="hidden" name="path" value="${currentPath}" />
      <input type="hidden" name="name" id="folderName" />
      <button class="btn-folder" type="submit">创建文件夹</button>
    </form>
    <a href="/zip?path=${encodeURIComponent(currentPath)}"><button class="btn-zip">打包下载ZIP</button></a>
  </div>

  <table>
    <tr><th>名称</th><th>类型</th><th>大小</th><th>操作</th></tr>
    ${files
      .map(
        (f) => `
        <tr>
          <td>${f.type === "folder"
            ? `<a href="/?path=${encodeURIComponent(path.join(currentPath, f.name))}" class="folder">${f.name}</a>`
            : `<span class="file">${f.name}</span>`}</td>
          <td>${f.type}</td>
          <td>${f.size}</td>
          <td>
            ${f.type === "file"
              ? `<a href="/download?path=${encodeURIComponent(currentPath)}&name=${encodeURIComponent(f.name)}"><button class="btn-zip">下载</button></a>`
              : ""}
            <form class="inline" action="/delete" method="post" onsubmit="return confirm('确定删除 ${f.name} 吗？')">
              <input type="hidden" name="path" value="${currentPath}" />
              <input type="hidden" name="name" value="${f.name}" />
              <button class="btn-delete" type="submit">删除</button>
            </form>
          </td>
        </tr>`
      )
      .join("")}
  </table>
</div>

<script>
function createFolder(form){
  const name = prompt("请输入新文件夹名称：");
  if(!name) return false;
  form.querySelector("#folderName").value = name;
  return true;
}
</script>
</body>
</html>`;
}

// 启动服务
// 修复端口解析逻辑，正确处理通过 npm scripts 传递的参数
const PORT_ARG = process.argv.find(arg => arg.startsWith('--port='));
const PORT = PORT_ARG 
  ? parseInt(PORT_ARG.split('=')[1])
  : 3000;

app.listen(PORT, () => {
  const ip = getLocalIP();
  console.log(`✅ 文件共享服务已启动：`);
  console.log(`📡 本地访问：http://localhost:${PORT}`);
  console.log(`🌐 局域网访问：http://${ip}:${PORT}`);
});
